import 'dart:convert';
import 'dart:io';

import 'package:gate_cli/utils/intl_view/command/edit_strings.dart';
import 'package:gate_cli/utils/intl_view/command/find_strings.dart';
import 'package:gate_cli/utils/intl_view/command/import_from_smartling.dart';
import 'package:gate_cli/utils/intl_view/command/submit_to_smartling.dart';
import 'package:gate_cli/utils/intl_view/utils/project_intl.dart';
import 'package:gate_cli/utils/intl_view/utils/project_string_finder.dart';
import 'package:gate_cli/utils/intl_view/utils/pull_smartling_flutter.dart';
import 'package:gate_cli/utils/intl_view/utils/smartling_intl.dart';

class IntlHTTPServer {
  static final IntlHTTPServer instance = IntlHTTPServer();

  Future<void> run({required String project}) async {
    final server = await HttpServer.bind(InternetAddress.loopbackIPv4, 18927);
    print('HTTP Server running on ${server.address.address}:${server.port}');

    Process.start('open', ['https://main.d36y6p0iuo1c8w.amplifyapp.com/']);

    await for (var request in server) {
      /// CORS
      request.response.headers.add('Access-Control-Allow-Origin', '*');
      request.response.headers.add('Access-Control-Allow-Methods', 'GET,POST,DELETE,PUT,OPTIONS');
      request.response.headers
          .add('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization');

      final path = request.uri.path;
      final method = request.method;
      final params = request.uri.queryParameters;
      final response = request.response;

      switch (method) {
        case 'GET':
          final result = _handlerGETRequest(path, params);
          if (result != null) {
            response.write(jsonEncode(result));
          }
          break;
        case 'POST':
          final bodyString = await utf8.decoder.bind(request).join();
          final body = jsonDecode(bodyString);
          final result = _handlerPOSTRequest(path, body);
          if (result != null) {
            response.write(jsonEncode(result));
          }
          break;
        case 'OPTIONS':
          response.close();
          continue;
        default:
          response.write('Hello, world! - $path - $method - $params');
      }

      response.close();
    }
  }

  Object? _handlerGETRequest(String path, Map<String, String> params) {
    switch (path) {
      case '/locales':
        return ProjectIntl.instance.arbFiles.keys.toList();
      case '/strings':
        final locale = params['locale'];
        if (locale != null) {
          final arbFile = ProjectIntl.instance.arbFiles[locale];
          if (arbFile != null) {
            arbFile.readStrings();
            return arbFile.strings;
          } else {
            return {};
          }
        } else {
          return {};
        }
      case '/smartling/arbs':
        return SmartlingIntl.instance.getArbNames();
      case '/smartling/associated_arbs':
        return getAssociatedSmartlingArbs();
      case '/submit/difference':
        final arbs = params['arbs']?.split(',');
        if (arbs == null) {
          return null;
        }
        return SubmitCommand.difference(associatedArbs: arbs);
      case '/smartling/import/translated_strings':
        final arbs = params['arbs']?.split(',');
        if (arbs == null) {
          return null;
        }
        return ImportCommand.listTranslatedStrings(associatedArbs: arbs);
      case '/smartling/target_arb':
        return getSubmitTargetSmartlingArb();
      case '/find/strings':
        return FindCommand.findStrings();
      case '/open_file':
        final path = params['path'];
        if (path != null) {
          Process.start('open', [path]);
        }
        break;
      case '/open_smartling_flutter':
        Process.start('open', [getSmartlingDirectory().path]);
        break;
      default:
    }
    return null;
  }

  Object? _handlerPOSTRequest(String path, Map<String, dynamic> body) {
    switch (path) {
      case '/create':
        final key = body['key'];
        final strings = body['strings'] as Map<String, dynamic>?;
        if (key != null && strings != null) {
          EditCommand.create(key: key, strings: strings.cast());
        }
        break;
      case '/modify':
        final key = body['key'];
        final strings = body['strings'] as Map<String, dynamic>?;
        if (key != null && strings != null) {
          EditCommand.modify(key: key, strings: strings.cast());
        }
        break;
      case '/delete':
        final key = body['key'];
        if (key != null) {
          EditCommand.delete(key: key);
        }
        break;
      case '/smartling/submit':
        final targetArb = body['target_arb'];
        final strings = body['strings'] as Map<String, dynamic>?;
        if (targetArb != null && strings != null) {
          return SubmitCommand.submit(targetArb, strings.cast());
        }
        break;
      case '/smartling/associate_arbs':
        final arbs = body['arbs'] as List<dynamic>?;
        if (arbs != null) {
          setAssociatedSmartlingArbs(arbs.cast());
        }
        break;
      case '/smartling/target_arb':
        final arb = body['arb'] as String?;
        if (arb != null) {
          setSubmitTargetSmartlingArb(arb);
        }
        break;
      case '/smartling/import/translated_strings':
        final arbs = body['arbs'] as List<dynamic>?;
        if (arbs != null) {
          ImportCommand.importTranslatedStrings(associatedArbs: arbs.cast());
        }
        break;
      case '/find/strings/import':
        final files = body['strings'] as List<dynamic>?;
        final keys = body['keys'] as Map<String, dynamic>?;
        if (files != null && keys != null) {
          FindCommand.import(
            files.map((e) => ProjectDartFile.fromJson(e)).toList(),
            keys.cast(),
          );
        }
        break;
      default:
    }
    return null;
  }
}
